﻿
/* Global variables */
var _jqGrids = new Array();

/* Data Types */
var _DataTypes = new Object();
    _DataTypes.Date     = "DateTime";
    _DataTypes.String   = "String";
    _DataTypes.Decimal  = "Decimal";
    _DataTypes.Integer  = "Integer";
    _DataTypes.Boolean  = "Boolean";

/* Edit Modes */
var _EditMode = new Object();
    _EditMode.Inline    = "Inline";
    _EditMode.Modal     = "Modal";

/* Formatters */
var _Formatters = new Object();
    _Formatters.DecimalFormatter                = _decimalFormatter;

var jqGridHelper = new Object();
/* Methods */
    jqGridHelper.createGridObject               = _createGridObject;
    jqGridHelper.setGridOpts                    = _setGridOpts;
    jqGridHelper.changeGridDataType             = _changeGridDataType;
    jqGridHelper.getGrid                        = _getGrid;
    jqGridHelper.getColModel                    = _getColModel;
    jqGridHelper.reloadGrid                     = _reloadGrid;
    jqGridHelper.addRowData                     = _addRowData;
    jqGridHelper.addNewRow                      = _addNewRow;
    jqGridHelper.editRow                        = _editSelectedRow;
    jqGridHelper.deleteRow                      = _deleteSelectedRow;
    jqGridHelper.cancelEdit                     = _cancelEditRow;
    jqGridHelper.getCurrentRowId                = _getCurrentRowId;
    jqGridHelper.getSelectedRowIds              = _getSelectedRowIds;
    jqGridHelper.setSelectedRows                = _setSelectedRows;
    jqGridHelper.toggleSelectedRows             = _toggleSelectedRows;
    jqGridHelper.validateDecimal                = _validateDecimal;
    jqGridHelper.getPostData                    = _getPostData;
    jqGridHelper.setPostData                    = _setPostData;
    jqGridHelper.setWidth                       = _setWidth;
    jqGridHelper.setHeight                      = _setHeight;
    jqGridHelper.adjustSizeToFitIntoDialog      = _adjustSizeToFitIntoDialog;
    jqGridHelper.toggleColumnVisibility         = _toggleColumnVisibility;
    jqGridHelper.getSelectListColumns           = _getSelectListColumns;
    jqGridHelper.bindSelectListColumns          = _bindSelectListColumns;
    jqGridHelper.getGridRowCellValue            = _getGridRowCellValue;
    jqGridHelper.checkForSelectedRow            = _checkForSelectedRow;
    jqGridHelper.getTotalRows                   = _getTotalRows;
    jqGridHelper.getTotalRowsPerPage            = _getTotalRowsPerPage;
    jqGridHelper.hideRowHeaderCheckbox          = _hideRowHeaderCheckbox;
    jqGridHelper.hideRowCheckbox                = _hideRowCheckbox;
    jqGridHelper.showRowCheckbox                = _showRowCheckbox;
    jqGridHelper.disableRowCheckbox             = _disableRowCheckbox;
    jqGridHelper.enableRowCheckbox              = _enableRowCheckbox;
    jqGridHelper.disableAllCheckboxes           = _disableAllCheckboxes;
    jqGridHelper.getRowCheckbox                 = _getRowCheckbox;
    jqGridHelper.getAllRowsCheckboxes           = _getAllRowsCheckboxes;
    jqGridHelper.getAllRows                     = _getAllRows;
    jqGridHelper.getRowHeader                   = _getRowHeader;
    jqGridHelper.unselectAllRows                = _unselectAllRows;
    jqGridHelper.unselectRow                    = _unselectRow;
    jqGridHelper.clearGridData                  = _clearGridData;
    jqGridHelper.destroyGrid                    = _destroyGrid;
    jqGridHelper.groupRows                      = _groupRows;
    jqGridHelper.removeRowGrouping              = _removeRowGrouping;
    jqGridHelper.expandAllRowGroups             = _expandAllRowGroups;
    jqGridHelper.getRowGroupHeaders             = _getRowGroupHeaders;
    jqGridHelper.setGroupedRowsHeaderStyles     = _setGroupedRowsHeaderStyles;
    jqGridHelper.getRowGroupHeaderText          = _getRowGroupHeaderText;
    jqGridHelper.setRowGroupHeaderText          = _setRowGroupHeaderText;
    jqGridHelper.groupColumns                   = _groupColumns;
    jqGridHelper.getColumnGroupHeaders          = _getColumnGroupHeaders;
    jqGridHelper.setGroupedColumnsHeaderStyles  = _setGroupedColumnsHeaderStyles;
    jqGridHelper.displaySearchDialog            = _displaySearchDialog;

    //add Data Types..
    jqGridHelper.DataTypes  = _DataTypes;

    //add Edit Modes..
    jqGridHelper.EditMode   = _EditMode;

    //add Formatters..
    jqGridHelper.Formatters = _Formatters;


    var isSafari = /Apple/.test(navigator.vendor);

function _createGridObject()
{
    /* jqGrid Instance Objects */
    var grid                            = new Object();
        grid.IdGrid                     = null;
        grid.IdPager                    = null;
        grid.IdColModel                 = null;
        grid.ColModel                   = null;
        grid.IdBtnAdd                   = null;
        grid.IdBtnEdit                  = null;
        grid.IdBtnDelete                = null;
        grid.IdBtnCancel                = null;
        grid.IdBtnConfirm               = null;
        grid.Width                      = null;
        grid.Height                     = null;
        grid.Title                      = null;
        grid.DefaultSortColumn          = null;
        grid.DefaultSortOrder           = null;
        grid.PageSizeList               = null;
        grid.DefaultPageSize            = null;

    /* jqGrid Instance Variables */
        //grid.CurrentRowId               = -1;
        grid.EditMode                   = _EditMode.Inline;
        //grid.fIsEditing                  = false;
        //grid.IsAdding                   = false;
        //grid.IsExporting                = false;

    /* jqGrid Properties */
        grid.AutoWidth                  = false;
        grid.LoadFiltersOnSearch        = false;
        grid.MultiSelect                = false;
        grid.MultiSelectMaxSelected     = 0;
        grid.CheckRows                  = false;
        grid.IsGroupingRows             = false;
        grid.IsGroupingColumns          = false;
        grid.GroupedRowsHeaderStyles    = null;
        grid.GroupedColumnsHeaderStyles = null;
        grid.LoadOnInitialization       = true;

    /* jqGrid Instance Urls & Params */
        grid.UrlGet                     = null;
        grid.UrlEdit                    = null;
        grid.UrlDelete                  = null;
        grid.GetParams                  = null;
        grid.EditParams                 = null;
        grid.DelParams                  = null;

    /* jqGrid Pager Buttons */
        grid.ShowSearch                 = false;
        grid.ShowRefresh                = false;
        grid.ShowExport                 = false;
        grid.ShowPrint                  = false;
        grid.ShowColumns                = false;

    /* jqGrid Instance Functions */
        grid.OnSelectRow                = null;
        grid.OnDoubleClick              = null;
        grid.OnEditFunction             = null;

        grid.OnAfterSaveEditFunction    = null;
        grid.OnLoadComplete             = null;

    /* jqGrid Extra Functions */
        grid.LoadFilters                = null;
        grid.OnExport                   = null;
        grid.OnPrint                    = null;

    return grid;
}

/*#region Initialization Functions*/
function _setGridOpts(gridOpts)
{
    var grid                            = new Object();

        /* jqGrid Instance Objects */
        grid.IdGrid                     = gridOpts.IdGrid;
        grid.IdPager                    = gridOpts.IdPager;
        grid.IdColModel                 = gridOpts.IdColModel;
        grid.ColModel                   = gridOpts.ColModel;
        grid.IdBtnAdd                   = gridOpts.IdBtnAdd;
        grid.IdBtnEdit                  = gridOpts.IdBtnEdit;
        grid.IdBtnDelete                = gridOpts.IdBtnDel;
        grid.IdBtnCancel                = gridOpts.IdBtnCancel;
        grid.IdBtnConfirm               = gridOpts.IdBtnConfirm;
        grid.Width                      = gridOpts.Width;
        grid.Height                     = gridOpts.Height;
        grid.Title                      = gridOpts.Title;
        grid.DefaultSortColumn          = !isEmpty(gridOpts.DefaultSortColumn) ? gridOpts.DefaultSortColumn : "Id";
        grid.DefaultSortOrder           = !isEmpty(gridOpts.DefaultSortOrder) ? gridOpts.DefaultSortOrder : "asc";
        grid.PageSizeList               = !isEmpty(gridOpts.PageSizeList) ? gridOpts.PageSizeList : [10, 20, 30, 50];
        grid.DefaultPageSize            = !isEmpty(gridOpts.DefaultPageSize) ? gridOpts.DefaultPageSize : 10;

        /* jqGrid Instance Variables */
        grid.CurrentRowId               = -1;
        grid.EditMode                   = gridOpts.EditMode;
        grid.IsEditing                  = false;
        grid.IsAdding                   = false;
        grid.IsExporting                = false;
        grid.Parameters                 = gridOpts.Parameters;

    /* jqGrid Properties */
        grid.AutoWidth                  = gridOpts.AutoWidth;
        grid.ShrinkToFit                = gridOpts.ShrinkToFit;
        grid.LoadFiltersOnSearch        = gridOpts.LoadFiltersOnSearch;
        grid.MultiSelect                = gridOpts.MultiSelect;
        grid.MultiSelectMaxSelected     = gridOpts.MultiSelectMaxSelected;
        grid.CheckRows                  = gridOpts.CheckRows;
        grid.IsGroupingRows             = false;
        grid.IsGroupingColumns          = false;
        grid.GroupedRowsHeaderStyles    = gridOpts.GroupedRowsHeaderStyles != null ? gridOpts.GroupedRowsHeaderStyles : { color: "blue", background: "lightcyan", "line-height": "26px" };
        grid.GroupedColumnsHeaderStyles = gridOpts.GroupedColumnsHeaderStyles != null ? gridOpts.GroupedColumnsHeaderStyles : { "font-style": "italic" };
        grid.LoadOnInitialization       = gridOpts.LoadOnInitialization != null ? gridOpts.LoadOnInitialization : true;

        /* jqGrid Instance Urls & Params */
        var pathName                    = getCurrentPageName();
        grid.UrlGet                     = pathName + "/" + gridOpts.UrlGet;
        grid.UrlEdit                    = pathName + "/" + gridOpts.UrlEdit;
        grid.UrlDelete                  = pathName + "/" + gridOpts.UrlDelete;
        grid.GetParams                  = gridOpts.GetParams;
        grid.EditParams                 = gridOpts.EditParams;
        grid.DelParams                  = gridOpts.DelParams;

        /* jqGrid Extra Functions */
        grid.LoadFilters                = gridOpts.LoadFilters;
        grid.OnExport                   = gridOpts.OnExportFn;
        grid.OnPrint                    = gridOpts.OnPrintFn;

        /* jqGrid Pager Buttons */
        grid.ShowSearch                 = gridOpts.ShowSearch;
        grid.ShowRefresh                = gridOpts.ShowRefresh;
        grid.ShowExport                 = gridOpts.ShowExport;
        grid.ShowPrint                  = gridOpts.ShowPrint;
        grid.ShowColumns                = gridOpts.ShowColumns;

        /* jqGrid Instance Functions */
        grid.OnSelectRow                = gridOpts.OnSelectRow;
        grid.OnDoubleClick              = gridOpts.OnDoubleClick;
        grid.OnEditFunction             = gridOpts.OnEditFn;
        grid.OnAfterSaveEditFunction    = gridOpts.OnAfterSaveEditFn;
        grid.OnLoadComplete             = gridOpts.OnLoadComplete;

    //add new Grid object to array of Grids..
    _jqGrids[_jqGrids.length] = grid;

    //set up jqGrid..
    _createGrid(grid);
    _setGridPager(grid);
    _setGridPagerExtensions(grid);
    _setGridPagerCustomIcons(grid);

    //add buttons click event handlers..
    if ( grid.EditMode == jqGridHelper.EditMode.Inline )
    {
        if ( !isEmpty(grid.IdBtnAdd) )
            $("#" + grid.IdBtnAdd).click(function () { _addNewRow(grid.IdGrid); });
        if ( !isEmpty(grid.IdBtnCancel) )
            $("#" + grid.IdBtnCancel).click(function () { _cancelEditRow(grid.IdGrid); });
        if ( !isEmpty(grid.IdBtnConfirm) )
            $("#" + grid.IdBtnConfirm).click(function () { _confirmEditRow(grid.IdGrid); });
        if ( !isEmpty(grid.IdBtnDelete) )
            $("#" + grid.IdBtnDelete).click(function () { _deleteSelectedRow(grid.IdGrid); });
    }
}
function getCurrentPageName()
{
    var pagePath = window.location.pathname;
    var arr = pagePath.split('/');
    var pageName = arr[arr.length - 1];
    return pageName;
}
function _createGrid(grid)
{
    // Set Defaults..

    if ( isEmpty(grid.AutoWidth) )
        grid.AutoWidth = true;

    if ( isEmpty(grid.MultiSelect) )
        grid.MultiSelect = false;

    if ( isEmpty(grid.DefaultSortColumn) )
        grid.DefaultSortColumn = "Id";

    if ( isEmpty(grid.DefaultSortOrder) )
        grid.DefaultSortOrder = "asc";

    var dataType = grid.LoadOnInitialization ? "json" : "local";

    $("#" + grid.IdGrid).jqGrid(
    {
        url: grid.UrlGet,
        mtype: "POST",
        datatype: dataType,
        jsonReader:
        {
            root: "rows",
            page: "page",
            total: "total",
            records: "records",
            repeatitems: true,
            cell: "cell",
            id: "id"
        },
        colNames: grid.ColNames,
        colModel: grid.ColModel,
        pager: "#" + grid.IdPager,
        rowNum: grid.DefaultPageSize,
        rowList: grid.PageSizeList, //[10, 20, 30, 50]
        sortname: grid.DefaultSortColumn, //Default SortColumn
        sortorder: grid.DefaultSortOrder, //Default SortOrder.
        loadtext: 'Cargando datos...',
        recordtext: "{0} - {1} de {2} resultados",
        emptyrecords: 'Sin resultados',
        pgtext: 'Página: {0} de {1}',
        /*
        width: grid.Width,
        height: grid.Height,
        */
        shrinkToFit: grid.ShrinkToFit,
        autowidth: grid.AutoWidth,
        caption: grid.Title,
        viewrecords: true, //Shows the RecordCount in the pager.
        multiselect: grid.MultiSelect,
        //multiboxonly: true,
        sortable: false, // allow/disable (true/false) column reorder by drag & drop
        serializeGridData: function(postData)
        {
            grid = _getGrid(grid.IdGrid);

            var fn = overloadFunction(_processGridPostData, grid.IdGrid, grid.IsExporting, grid.Parameters);
            grid.IsExporting = false;
            return fn(postData);
        },
        grouping: true,
        groupingView:
        {
            groupField: [""],
            groupColumnShow: [false],
            groupText: ["<b>{0}</b> - {1} ítem(s)"]
        },
        serializeRowData: function(postData)
        {
            grid = _getGrid(grid.IdGrid);

            var fn = overloadFunction(_processRowPostData, grid.IdGrid);
            return fn(postData);
        },
        beforeSelectRow: function(rowid, e)
        {
            grid = _getGrid(grid.IdGrid);

            if (grid.MultiSelect == true)
            {
                if (grid.MultiSelectMaxSelected > 0)
                {
                    var acceptSelection = true;

                    //if (grid.MultiSelectMaxSelected > selectedIds.length) {
                    //    acceptSelection = false;
                    //}

                    var rowIdToBeSelected = rowid;

                    var selectedIds = _getSelectedRowIds(grid.IdGrid, true);

                    grid.CurrentRowId = selectedIds[0];

                    if (grid.CurrentRowId == rowIdToBeSelected)
                    {
                        acceptSelection = false;
                        _unselectRow(grid.IdGrid, grid.CurrentRowId);
                    }
                    else
                    {
                        // Remove all selections
                        _unselectAllRows(grid.IdGrid);
                    }

                    return(acceptSelection);                    
                }

                //// Prevents selecting on a row by clicking on it. Only checkbox has control over row selection.
                //var $myGrid = $(this);
                //var i = $.jgrid.getCellIndex($(e.target).closest('td')[0]);
                //var cm = $myGrid.jqGrid('getGridParam', 'colModel');
                //return (cm[i].name === 'cb');
            }
            else
            {
                //This event fire when the user clicks on the row, but before selecting it..
                if ( grid.IsEditing || grid.IsAdding )
                {
                    return false;
                }
                else
                {
                    grid.CurrentRowId = rowid;
                    return true;
                }
            }
        },
        onSelectRow: function (selectedRowId)
        {
            var selectedIds = _getSelectedRowIds(grid.IdGrid, grid.MultiSelect ? true : false);
            //grid.CurrentRowId = selectedRowId;            
            grid.CurrentRowId = selectedIds[0];

            if ( !isEmpty(grid.OnSelectRow) )
                grid.OnSelectRow.call(this, selectedRowId);
        },
        ondblClickRow: function(id)
        {
            grid = _getGrid(grid.IdGrid);

            //Inline Edit
            if ( grid.EditMode == _EditMode.Inline )
            {
                if ( grid.MultiSelect == true )
                {
                    //find jqGrid element..
                    var objGrid = $("#" + grid.IdGrid );
                    //unselect all..
                        _unselectAllRows(grid.IdGrid);
                    //select current row..
                        objGrid.jqGrid('setSelection', id);
                }

                if ( grid.IsEditing || grid.IsAdding )
                    return;

                grid.CurrentRowId = id;
                grid.IsEditing = true;

                _editSelectedRow(grid.IdGrid);

                if ( !isEmpty(grid.IdBtnAdd) )
                    $("#" + grid.IdBtnAdd).hide();
                if ( !isEmpty(grid.IdBtnCancel) )
                    $("#" + grid.IdBtnCancel).show();
                if ( !isEmpty(grid.IdBtnConfirm) )
                    $("#" + grid.IdBtnConfirm).show();
                if ( !isEmpty(grid.IdBtnDelete) )
                    $("#" + grid.IdBtnDelete).show();
            }
            
            //Modal Edit..
            if ( grid.EditMode == _EditMode.Modal )
            {
            }

            //grid.CurrentRowId = id;
            if (!isEmpty(grid.OnDoubleClick))
                grid.OnDoubleClick.call(this, id);
        },
        onSelectAll: function(aRowids, status) //This event fires when multiselect option is true and you click on the header checkbox
        {
            /*
                aRowids array of the selected rows (rowid's). 
                status - boolean variable determining the status of the header check box - true if checked, false if not checked. 
                Note that the aRowids alway contain the ids when header checkbox is checked or unchecked.
            */
        },
        loadError: function (xmlHttpRequest, status, error)
        {
            handleError( xmlHttpRequest, status, error );
        },
        loadComplete: function(data)
        {
            grid = _getGrid(grid.IdGrid);

            if ( grid.IsGroupingRows )
            {
                _setGroupedRowsHeaderStyles(grid.IdGrid);

                if ( grid.MultiSelect )
                    _createGroupCheckColumns(grid.IdGrid);
            }

            if ( grid.IsGroupingColumns )
            {
                __fixGroupedColumnsWidth(grid.IdGrid);

                _setGroupedColumnsHeaderStyles(grid.IdGrid);
            }
            
            if ( data.d != null )
                data = jQuery.parseJSON(data.d);

            if ( !isEmpty(grid.OnLoadComplete))
                grid.OnLoadComplete.call(this, data);

            if ( grid.CheckRows == true )
                _checkRows(grid.IdGrid, data);

            _resetButtons(grid.IdGrid);

            // Required if LoadOnInitialization = true. Otherwise no further requests will be made to the server
            _changeGridDataType(grid.IdGrid, "json");
        },
        gridComplete: function()
        {
            if (grid.MultiSelect == true)
            {
                if (grid.MultiSelectMaxSelected > 0)
                {
                    // Disable "Un/SelectAll" checkbox
                    var cb = $("#cb_" + grid.IdGrid);
                    if (cb.length > 0)
                        cb.css("display", "none");
                }
            }
        },
        afterInsertRow: function (rowid, data, rowelem)
        {
            /*
            if (data.Status == "Rejected")
            {
                $(this).jqGrid('setRowData', rowid, false, { color: "red" });
                //$("#" + rowid).children("td").css('background-color', "red");
                //$("#" + rowid).css("background-color", "red");
            }
            */
        }
    });

    _removeRowGrouping(grid.IdGrid);

    //set grid's width & height..
    if ( grid.Height )
        _setHeight(grid.IdGrid, grid.Height);

    //if ( grid.Width )
    //    _setWidth(grid.IdGrid, (grid.Width));
    _setWidth(grid.IdGrid, "99%");
}
function _changeGridDataType(idGrid, dataType)
{
    $("#" + idGrid).jqGrid('setGridParam', { datatype: dataType });//.trigger('reloadGrid');
}
function _createGroupCheckColumns(idGrid)
{
    var grid = _getGrid(idGrid);
    if (grid.IsGroupingRows == true)
    {        
        var jqGridGroupClass = "jqgroup";
        var jqGridRowClass   = "jqgrow";
        var groupHeaders = $("." + jqGridGroupClass);

        for (var i = 0; i < groupHeaders.length; i++)
        {       
            var check = $("<span style='float: left; margin: 6px 5px 0px 13px;' ><input type='checkbox' class='chk_" + idGrid + "' /></span>");
                check.click
                (
                    function()
                    {
                        //var checkColumnName = "Check";
                        var container = $(this);
                        var groupCheck = $(container.children()[0]);
                        var isChecked = groupCheck.prop("checked");
                        var row = container.parent().parent();
                            row = row.next();
                        while ( !row.hasClass(jqGridGroupClass) && row.length > 0 ) //row.hasClass(jqGridRowClass)
                        {
                            var rowId = row.attr("id");
                            //var chk = $('#' + rowId + ' td[aria-describedby="' + idGrid + '_' + checkColumnName + '"] input[type="checkbox"]');
                            //if ( chk.length > 0 )
                            //{
                            //    chk.prop("checked", isChecked);
                            //    row = row.next();
                            //}
                            var onSelectRowFn = null;
                            $("#" + idGrid).jqGrid('setSelection', rowId, onSelectRowFn, isChecked);
                            row = row.next();
                        }
                    }
                ); 
            var groupHeader = _getRowGroupHeaderText(idGrid, i);
                groupHeader.parent().prepend(check);
        }
    }
}
function _resetButtons(idGrid)
{
    var grid = _getGrid(idGrid);
        grid.IsEditing  = false;
        grid.IsAdding   = false;

    if ( !isEmpty(grid.IdBtnAdd) )
        $("#" + grid.IdBtnAdd).show();
    if ( !isEmpty(grid.IdBtnCancel) )
        $("#" + grid.IdBtnCancel).hide();
    if ( !isEmpty(grid.IdBtnConfirm) )
        $("#" + grid.IdBtnConfirm).hide();
    if ( !isEmpty(grid.IdBtnDelete) )
        $("#" + grid.IdBtnDelete).hide();
}
function _setColModel(idGrid)
{
    var grid = _getGrid(idGrid);

    var colModel = { Cols: [] };
    var model = $("#" + grid.IdGrid).getGridParam().colModel;
    for (i = 0; i < model.length; i++)
    {
        var column = { name: '', type: '', label: '' };
        if (model[i].index != null)
        {
            column.name     = model[i].index;
            column.type     = ( model[i].dataType != null ? model[i].dataType : 'String' );
            column.label    = model[i].label;
            colModel.Cols.push(column);
        }
    }
    jsonColModel = JSON.stringify(colModel);
    $("#" + grid.IdColModel).val(jsonColModel);
}
function _getColModel(idGrid)
{
    var grid = _getGrid(idGrid);
    var colModel = $("#" + grid.IdGrid).getGridParam().colModel;
    //var colModel = $("#" + grid.IdGrid)[0].p.colModel;
    return colModel;
}
function _getColModelColumn(idGrid, propertyName, propertyValue)
{
    var columnInfo = null;
    var colModel = _getColModel(idGrid);
    for (var i = 0; i < colModel.length; i++)
    {
        if (colModel[i][propertyName] == [propertyValue])
        {
            columnInfo = colModel[i];
            break;
        }
    }
    return columnInfo;
}
function _setGridPager(grid)
{
    /*
       searchOpts:
       {
         caption: "Search...",
         Find: "Find",
         Reset: "Reset",
         odata : ['equal', 'not equal', 'less', 'less or equal','greater','greater or equal', 'begins with','does not begin with','is in','is not in','ends with','does not end with','contains','does not contain'],
         groupOps: [ { op: "AND", text: "all" }, { op: "OR", text: "any" } ],
         matchText: " match",
         rulesText: " rules"
       },
       editOpts:
       {
         addCaption: "Add Record",
         editCaption: "Edit Record",
         bSubmit: "Submit",
         bCancel: "Cancel",
         bClose: "Close",
         saveData: "Data has been changed! Save changes?",
         bYes : "Yes",
         bNo : "No",
         bExit : "Cancel",
      },
      viewOpts:
      {
        caption: "View Record",
        bClose: "Close"
      },
      delOpts:
      {
        caption: "Delete",
        msg: "Delete selected record(s)?",
        bSubmit: "Delete",
        bCancel: "Cancel"
      },
      nav :
      {
        edittext: "",
        edittitle: "Edit selected row",
        addtext:"",
        addtitle: "Add new row",
        deltext: "",
        deltitle: "Delete selected row",
        searchtext: "",
        searchtitle: "Find records",
        refreshtext: "",
        refreshtitle: "Reload Grid",
        alertcap: "Warning",
        alerttext: "Please, select row",
        viewtext: "",
        viewtitle: "View selected row"
      }
    */

    var searchOpts =
    {
        drag: true,
        resize: false,
        jqModal: true,
        overlay: 40,
        closeOnEscape: true,
        showOnLoad: false,
        width: 450,
        height: "auto",
        caption: "Filtrar..",
        Find: "Buscar",
        Reset: "Resetear",
        sopt: ['eq','ne','lt','le','gt','ge','bw','bn','in','ni','ew','en','cn','nc','nu','nn'],
        odata: ['equal','not equal', 'less', 'less or equal','greater','greater or equal', 'begins with','does not begin with','is in','is not in','ends with','does not end with','contains','does not contain','is null','is not null'],
        multipleSearch: false,
        multipleGroup: false,
        recreateForm: false,
        onInitializeSearch: function() { }
    };

    if ( isEmpty(grid.ShowSearch) )
        grid.showSearch = false;

    if ( isEmpty(grid.ShowRefresh) )
        grid.showRefresh = false;

    $("#" + grid.IdGrid).jqGrid
    (
        'navGrid', "#" + grid.IdPager,
        {
            view: false, edit: false, add: false, del: false, search: grid.ShowSearch, searchtext: "Buscar&nbsp;", refresh: grid.ShowRefresh, refreshtext: "Actualizar&nbsp;"
        },
        {}, //settings for edit..
        {}, //settings for add..
        {}, //settings for delete..
        searchOpts,  //settings for search..
        {}  //settings for view..
    );

    if ( !isEmpty(grid.ShowExport) )
    {
        $("#" + grid.IdGrid).navGrid("#" + grid.IdPager)
        .navButtonAdd
        (
            "#" + grid.IdPager,
            {
                caption: "Export&nbsp;",
                buttonicon: "btnExport",
                id: "btnExport",
                onClickButton: function()
                {
                    //invoke Export function..
                    grid.OnExport.call(this);
    
                    //get postData to be sent to server..
                    var postData = _getPostData(grid.IdGrid);

                    //set IsExporting flag to TRUE..
                    grid.IsExporting = true;

                    //overload _processGridPostData function to add IsExporting parameter..
                    var fn = overloadFunction(_processGridPostData, grid.IdGrid, grid.IsExporting);
                    
                    //invoke overloaded function and retrieve modified postData..
                    postData = fn(postData);

                    //reload grid to force modified postData be sent to server..
                    _reloadGrid(grid.IdGrid);
                },
                position: "last"
            }
        );
    }

    if ( !isEmpty(grid.ShowPrint) )
    {
        $("#" + grid.IdGrid).navGrid("#" + grid.IdPager)
        .navButtonAdd
        (
            "#" + grid.IdPager,
            {
                caption: "Print&nbsp;",
                buttonicon: "btnPrint",
                id: "btnPrint",
                onClickButton: function()
                {
                    grid.OnPrint.call(this);
                },
                position: "last"
            }
        );
    }

    if ( !isEmpty(grid.ShowColumns) )
    {
        $("#" + grid.IdGrid).navGrid("#" + grid.IdPager)
        .navButtonAdd
        (
            "#" + grid.IdPager,
            {
                caption: "Columns",
                buttonicon: "btnReorder",
                id: "btnReorder",
                onClickButton: function()
                {
                    $("#" + grid.IdGrid).jqGrid('columnChooser');                
                },
                position: "last"
            }
        );
    }

}
function _setGridPagerExtensions(grid)
{
    $.extend($.jgrid.edit,
    {
        ajaxEditOptions: { contentType: "application/json" },
        recreateForm: true,
        serializeEditData: function (postData)
        {
            return JSON.stringify(postData);
        }
    });
    $.extend($.jgrid.del,
    {
        ajaxDelOptions: { contentType: "application/json" },
        serializeDelData: function (postData)
        {
            return JSON.stringify(postData);
        }
    });
}
function _setGridPagerCustomIcons(grid)
{
    var btnSearch = $(".ui-icon.ui-icon-search");
        btnSearch.removeClass("ui-icon-search");
        btnSearch.addClass("btnSearch");

    var btnRefresh = $(".ui-icon.ui-icon-refresh");
        btnRefresh.removeClass("ui-icon-refresh");
        btnRefresh.addClass("btnRefresh");
}
function _reloadGrid(idGrid)
{
    //reset buttons..
    var grid = _getGrid(idGrid);

    _changeGridDataType(idGrid, "json");
/*
    if ( grid.EditMode == jqGridHelper.EditMode.Inline )
    {
        _resetButtons(idGrid);
    }
*/
    //reload grid..
    //$("#" + idGrid).trigger("reloadGrid");
    $("#" + idGrid).trigger("reloadGrid", [{page:1}]); // always set current page back to #1
}
function _checkRows(idGrid, data)
{
    if (data.rows.length > 0)
	{
		for (var i = 0; i < data.rows.length; i++)
		{
            if ( (data.rows[i].cell[0].toLowerCase() == 'true') || (data.rows[i].cell[0].toLowerCase() == "1") )
			{
                $("#" + idGrid).jqGrid('setSelection', data.rows[i].id);
            }
        }
	}
}
//#endregion

/*#region Add/Edit Row Functions */
function _checkForSelectedRow(currentRowId)
{
    if ( currentRowId == undefined || currentRowId == "0" || currentRowId <= 0 )
        return false;
    else
        return true;
}
function _cancelEditRow(idGrid)
{
    var grid = _getGrid(idGrid);

        grid.IsEditing = false;
        grid.IsAdding  = false;

    if ( grid.EditMode == _EditMode.Inline )
    {
        _resetButtons(idGrid);
    }

    if (grid.CurrentRowId == -1)
        _deleteRow(grid.IdGrid, -1);
    else
        $("#" + grid.IdGrid).jqGrid('restoreRow', grid.CurrentRowId);
}
function _confirmEditRow(idGrid)
{
    var grid = _getGrid(idGrid);
        grid.IsEditing = false;
        grid.IsAdding  = false;

    _resetButtons(idGrid);        

    var onEdit              = overloadFunction(_setGridRowCellsControls, grid.IdGrid);
    var onSuccessEdit       = overloadFunction(_onSuccessEdit, grid.IdGrid);
    var onAfterSaveEdit     = overloadFunction(_onAfterSaveEdit, grid.IdGrid);
    var onErrorEdit         = overloadFunction(_onErrorEdit, grid.IdGrid);
    var onAfterErrorRestore = overloadFunction(_onAfterErrorRestore, grid.IdGrid);

    $("#" + grid.IdGrid).jqGrid('saveRow', grid.CurrentRowId, onSuccessEdit, grid.UrlEdit, grid.EditParams, onAfterSaveEdit, onErrorEdit, onAfterErrorRestore);
}
function _deleteRow(idGrid, rowId)
{
    $("#" + idGrid).delRowData(rowId);

    _resetButtons(idGrid);
}
function _deleteSelectedRow(idGrid)
{
    var grid = _getGrid(idGrid);
    var options =
    {
        top: 0,
        left: 0,
        width: 300,
        heigth: 200,
        modal: true,
        drag: false,
        msg: "Delete selected row(s)",
        caption: "Delete?",
        bSubmit: "Delete",
        bCancel: "Cancel",
        url: grid.urlDelete,
        reloadAfterSubmit: true,
        delData: { id: grid.CurrentRowId }
    };
    $("#" + grid.IdGrid).jqGrid('delGridRow', grid.CurrentRowId, options);
}
function _addRowData(idGrid, rowIdColName, data)
{
    /*
        addRowData( rowid, data, [position], [srcrowid] )
    
        Inserts a new row with id = rowid containing the data in data (an object) at the position specified (first in the table, last in the table or before or after the row specified in srcrowid).
        The syntax of the data object is: {name1:value1,name2: value2…} where name is the name of the column as described in the colModel and the value is the value. 
        This method can insert multiple rows at once. In this case the data parameter should be array defined as 
        [{name1:value1,name2: value2…}, {name1:value1,name2: value2…} ] and the first option rowid should contain the name from data object which should act as id of the row.
        It is not necessary that the name of the rowid in this case should be a part from colModel.
    */
    return $("#" + idGrid).addRowData(rowIdColName, data);
}
function _addNewRow(idGrid)
{
    var grid = _getGrid(idGrid);

    if (grid.IsEditing || grid.IsAdding)
        return;

    var rowId = -1;

    var jSONdata = "";
    var colModel = $("#" + grid.IdGrid).getGridParam().colModel;
    for (var i = 0; i < colModel.length; i++)
    {
        var column = colModel[i];
        if ( column.hidden == false && column.editable == true )
        {
            if (jSONdata.length == 0)
                jSONdata = "'" + column.name + "': '" + _setDefaultValue(column) + "'";
            else
                jSONdata += ", '" + column.name + "': '" + _setDefaultValue(column) + "'";
        }
    }
    jSONdata = "{ " + jSONdata + " }";
    eval("var data = " + jSONdata);
    var position = '';
    var targetRowId = '';

    //add new row..
    var success = $("#" + grid.IdGrid).addRowData(rowId, data, position, targetRowId);
    if (success)
    {
        grid.IsAdding = true;

        //set new row as selected..
        $("#" + grid.IdGrid).jqGrid('setSelection', rowId);

        //set inline edit on new row..
        grid.CurrentRowId = rowId;
        _editSelectedRow(grid.IdGrid);

        if ( grid.EditMode == _EditMode.Inline )
        {
            if ( !isEmpty(grid.IdBtnAdd) )
                $("#" + grid.IdBtnAdd).hide();
            if ( !isEmpty(grid.IdBtnCancel) )
                $("#" + grid.IdBtnCancel).show();
            if ( !isEmpty(grid.IdBtnConfirm) )
                $("#" + grid.IdBtnConfirm).show();
            //if ( !isEmpty(grid.IdBtnDelete) )
                //$("#" + grid.IdBtnDelete).show();
        }

    }
}
function _setDefaultValue(column)
{
    switch ( column.dataType.toLowerCase() )
    {
        case "datetime":
            return Helpers.DateTimeHelper.GetCurrentDate();
            break;
        case "decimal":
            return 0;
            break;
        case "integer":
            return 0;
            break;
        case "string":
            return "";
            break;
        default:
            return "";
            break;
    }
}
function _editSelectedRow(idGrid)
{
    var grid = _getGrid(idGrid);

    //var onEditFunction = overloadFunction(_setGridRowCellControl, "datepicker", "Date", _jqGrid_IdGrid);
    var onEdit              = overloadFunction(_setGridRowCellsControls, grid.IdGrid);
    var onSuccessEdit       = overloadFunction(_onSuccessEdit, grid.IdGrid);
    var onAfterSaveEdit     = overloadFunction(_onAfterSaveEdit, grid.IdGrid);
    var onErrorEdit         = overloadFunction(_onErrorEdit, grid.IdGrid);
    var onAfterErrorRestore = overloadFunction(_onAfterErrorRestore, grid.IdGrid);

    $("#" + grid.IdGrid).jqGrid
    (
        'editRow',
        grid.CurrentRowId,  //rowid
        true,               //keys
        onEdit,             //oneditfunc
        onSuccessEdit,      //succesfunc
        grid.UrlEdit,       //url
        grid.EditParams,    //extraparam
        onAfterSaveEdit,    //onAfterSaveEditFunction
        onErrorEdit,        //errorfunc
        onAfterErrorRestore //afterrestorefunc
    );

    //invoke OnEdit function passed as parameter..
    if ( !isEmpty(grid.OnEditFunction) )
        grid.OnEditFunction.call();

    //set row properties when editing..
    _setRowPropertiesForEdit(grid.IdGrid);
}
function _setRowPropertiesForEdit(idGrid)
{
    var grid = _getGrid(idGrid);

    //get current Row (and set its height)..
    var currentRow = $('tr[id="' + grid.CurrentRowId + '"]', "#" + idGrid);
    //currentRow.height(50);

    //If MultiSelect is true, first column should be omitted..
    var firstColIndex = 0;
    if ( grid.MultiSelect == true )
        firstColIndex = 1;

    //set focus on first visible column..
    var firstCol = currentRow.children("td:visible").children()[firstColIndex];

    _setGridRowCellFocus(grid.IdGrid, grid.CurrentRowId, firstCol.name);

    //set resize restrictions on TextArea inputs..
    var txt = currentRow.find('textarea');
    $.each(txt, function (index, item)
    {
        //$("#" + item.id).height(50);
        //$("#" + item.id).width(120);
        $("#" + item.id).addClass('resizeOnlyVertical');
    });
}
function _onSuccessEdit(idGrid, xmlHttpResponse)
{
    if (xmlHttpResponse.status != 200 || xmlHttpResponse.statusText != "OK")
        return false;   //onErrorEdit function will be called..
    else
        return true;    //onAfterSaveEdit function will be called..
}
function _onAfterSaveEdit(idGrid, xmlHttpResponse)
{
    var grid = _getGrid(idGrid);

        grid.IsEditing = false;
        grid.IsAdding = false;

    if ( grid.EditMode == _EditMode.Inline )
    {
        _resetButtons(idGrid);
    }

    //reload Grid..
    _reloadGrid(grid.IdGrid);

    //invoke OnAfterSaveEdit function passed as parameter..
    if ( !isEmpty(grid.OnAfterSaveEditFunction) )
        grid.OnAfterSaveEditFunction.call();
}
function _onErrorEdit(idGrid, rowId, xmlHttpResponse)
{
    if (xmlHttpResponse.status != 200 || xmlHttpResponse.statusText != "OK")
    {
        var exception = jQuery.parseJSON(xmlHttpResponse.responseText);
            exception.Message = "Error raised on Grid: " + idGrid + ", Row Id: " + rowId + "\n" + exception.Message;
        Helpers.NotificationHelper.showError(exception);
    }
    //onAfterErrorRestore function will be called..
}
function _onAfterErrorRestore(idGrid, rowId)
{
    var grid = _getGrid(idGrid);

        grid.IsEditing = false;
        grid.IsAdding = false;

    if ( grid.EditMode == _EditMode.Inline )
    {
        _resetButtons(idGrid);
    }

    _reloadGrid(grid.IdGrid);
}
function _getGrid(idGrid)
{
    var grid = null;
    for(var i=0; i < _jqGrids.length; i++)
    {
        grid = _jqGrids[i];
        if (grid.IdGrid == idGrid)
            break;
    }
    return grid;
}
//#endregion

/*#region Process GridPostData & RowPostData Functions */
function _getPostData(idGrid)
{
    return $("#" + idGrid).jqGrid("getGridParam", "postData");
}
function _setPostData(idGrid, postData)
{
    $("#" + idGrid).jqGrid('setGridParam', { search: true, postData: postData });
}
function _processGridPostData(idGrid, isExport, parameters, postData)
{    
    var grid = _getGrid(idGrid);

    var data = "{ }";

    var colModel = $("#" + grid.IdColModel).val();
    if (colModel.length == 0)
    {
        _setColModel(grid.IdGrid);
        colModel = $("#" + grid.IdColModel).val();
    }

    var filters = '';

	//delete unwanted parameters..
	if (typeof postData.nd !== undefined)
	    delete postData.nd;

	//invoke grid's load filters function..
	var loadFilters = "";
	var loadFiltersOnSearch = false;

	if ( !isEmpty(grid.LoadFilters) )
	{
	    loadFilters = grid.LoadFilters.call(this);
        loadFiltersOnSearch = grid.LoadFiltersOnSearch;
    }


	//if searching..
	if ( postData._search )
    {
	    filters = postData.filters;
	    if ( filters == undefined || filters == '' )
        {
            var rules = [];
            if ( loadFilters.length > 0 )
            {
                rules = jQuery.parseJSON(loadFilters);
            }
            var condicionBusqueda =
            {
                condition: "AND",
                set:
                [
                    { match: "AND", field: postData.searchField, op: postData.searchOper, data: postData.searchString }
                ]
            };
            rules.push( condicionBusqueda );
            loadFilters = JSON.stringify(rules);
	    }
	}

    if ( loadFilters.length > 0 )
    {
        loadFilters = '{ "rules":' + loadFilters + '}';
        filters = loadFilters;
    }

    data =  "{ 'pageSize':'" + postData.rows +
            "','currentPage':'" + postData.page +
            "','sortColumn':'" + postData.sidx +
            "','sortOrder':'" + postData.sord +
	        "','search':'" + true +
            "','searchFilter':'" + filters +
            "','colModel':'" + colModel + 
            "','isExport':'" + isExport +
            "','parameters':'" + parameters;

    if ( !isEmpty(grid.GetParams) )
        data += "', " + grid.GetParams + "}";
    else
        data += "'}";

	return data;
}
function _processRowPostData(idGrid, postData)
{
    var grid = _getGrid(idGrid);

    var data = "";

    //get colModel..
    var colModel = $("#" + grid.IdGrid).getGridParam().colModel;

    //loop through all columns..
    for (var i = 0; i < colModel.length; i++)
    {
        var column = colModel[i];
        //only consider those marked as "editable: true"
        if (column.editable)
        {
            if (data.length == 0)
                data  = "'"   + column.name + "':'" + postData[column.name] + "'";
            else
                data += ", '" + column.name + "':'" + postData[column.name] + "'";
        }
    }
    //add id parameter..
    data += ", 'id':'" + postData.id + "'";
    return "{" + data + "}";
}
//#endregion

/*#region GridRowCell Functions */
function _setSelectedRows(idGrid, rowIds, toggleCheckedRows)
{
    if ( toggleCheckedRows != true )
        _unselectAllRows( idGrid );

    _toggleSelectedRows( idGrid, rowIds );
}
function _toggleSelectedRows(idGrid, rowIds)
{
    for(var i=0; i < rowIds.length; i++)
    {
        $("#" + idGrid).jqGrid('setSelection', rowIds[i] );
    }
}
function _unselectRow(idGrid, idRow) {
    $("#" + idGrid).jqGrid('setSelection', idRow);
}
function _unselectAllRows( idGrid )
{
    $("#" + idGrid).jqGrid('resetSelection');
}
function _getSelectedRowIds(idGrid, hasCheckbox)
{
    var selectedRowIds = new Array();
    if (hasCheckbox == true)
    {
        var checked = _getAllRowsCheckboxes( idGrid );
        for (var i = 0; i < checked.length; i++)
        {
            var row = $(checked[i]).parent().parent();
            if (row != null)
            {
                var rowId = row.attr("id");
                selectedRowIds.push( rowId );
            }
        }
    }
    else
    {
        selectedRowIds = $("#" + idGrid).jqGrid('getGridParam', 'selarrrow');
    }
    return selectedRowIds;
}
function _getCurrentRowId(idGrid)
{
    var grid = _getGrid(idGrid);
    return grid.CurrentRowId;
}
function _getGridRowCellValue(idGrid, rowId, cellName)
{
    var grid = _getGrid(idGrid);
    var value = "";
    if ( (grid.EditMode == _EditMode.Inline) && (grid.IsEditing) )
    {
        var cell = $('#' + rowId + '_' + cellName, "#" + idGrid);
        value = cell.val();
    }
    else
    {
        var rowData = $("#" + idGrid).getRowData(rowId);
        value = rowData[cellName];
    }
    return value;
}
function _setGridRowCellFocus(idGrid, rowId, colId)
{
    var txt = $("#" + rowId + "_" + colId, "#" + idGrid);
    if ( txt[0] != null )
    {
        txt[0].blur();
        txt[0].focus();
    }
}
function _setGridRowCellControl(control, colName, idGrid, idRow)
{
    var cell = $("#" + idRow + "_" + colName, "#" + idGrid);
    switch (control.toLowerCase())
    {
        case "datepicker":
            cell.datepicker({ dateFormat: Helpers.LocalizationHelper.DateFormat.replace("yyyy", "yy"), showAnim: 'drop' });
            break;
    }
}
function _setGridRowCellsControls(idGrid, idRow)
{
    var colModel = $("#" + idGrid).getGridParam().colModel;
    for (var i = 0; i < colModel.length; i++)
    {
        var column = colModel[i];
        if (!column.hidden && column.editable)
        {
            var colName = column.name;
            var colType = column.dataType;
            var cell = $("#" + idRow + "_" + colName, "#" + idGrid);
            switch (colType.toLowerCase())
            {
                case "datetime":
                    cell.datepicker({ dateFormat: Helpers.LocalizationHelper.DateFormat.replace("yyyy", "yy"), showAnim: 'drop' });
                    break;
            }
        }
    }
}
function getGridSearchOptions_Date()
{
    var opts =
    {
        sopt: ['eq', 'ne', 'gt', 'ge', 'lt', 'le'],
        dataInit: function (element) { $(element).datepicker({ dateFormat: Helpers.LocalizationHelper.DateFormat }); }
    };
    return opts;
}
//#endregion

/*#region HTML Select Lists Functions */
//PLEASE NOTICE: this method should only be called when current row's onEdit (inlineEdit) event is fired..
function _bindSelectListColumns(idGrid, currentRowId, bindings, triggerListId, triggerListIndex, cascadeActions)
{
    //get all select lists columns defined on grid..
    var selectCols = _getSelectListColumns(idGrid);

    var prevBindingListId   = undefined;    //id of parent binding list..
    var selectedParentId    = undefined;    //id of parent..
    var targetListId        = undefined;    //id of binding list to be filled..   
    var selectedTargetId    = undefined;    //current value on row (to be selected on target list, once fully loaded)
    
    //loop through collection of bindings..
    for(var i=0; i < bindings.length; i++)
    {
        //for each group of secuencial bindings..
        for (var j=0; j < bindings[i].length; j++)
        {
            var bindingListId = bindings[i][j];
            var selectColumn  = selectCols[j];

            //if binding and column matches..
            if ( (selectColumn + "_List").toLowerCase() == bindingListId.toLowerCase() )
            {
                //get id of current row's select list..
                targetListId = currentRowId + "_" + selectColumn;
                
                /*  [Fix #04-05-2012.16:57]
                    When jqGrid creates Select Lists elements based upon column fields, if targetListId has no elements loaded,
                    Select List is created without an Id. This fix addresses this issue locating the Select List by its "aria-describedby" attribute.
                */
                if ( $("#" + targetListId).length == 0 )
                    $("td[aria-describedby='" + idGrid + "_" + selectColumn + "']").children(":first").attr("id", targetListId);
                /* End of [Fix #04-05-2012.16:57] */

                //get value from current column on row being edited..
                selectedTargetId = $("#" + idGrid).jqGrid('getCell', currentRowId, selectColumn + 'Id');

                //if the current bindingListId is the one of the list that has triggered the binding..
                if ( (triggerListId == undefined && triggerListIndex == undefined) || ( (targetListId == triggerListId) || (j > triggerListIndex) ) )
                {
                    if ( triggerListId != undefined )
                    {
                        if (triggerListId == targetListId)
                            selectedTargetId = $("#" + targetListId).val();
                        else
                            selectedTargetId = -1;
                    }

                    //fill target list with corresponding data..
                    if ( selectedParentId == undefined )
                        selectedParentId = -1;

                    //get selected id on target list..
                    if ( targetListId != triggerListId )
                        selectedTargetId = Helpers.SelectListHelper.setSelectListBasedOnSelectionBindings(bindingListId, selectedParentId, targetListId, selectedTargetId);

                    var htmlSelect = $("#" + targetListId);
                        htmlSelect.unbind('change');
                    var onChangeFn = overloadFunction(doRecursiveBinding, idGrid, currentRowId, bindings, j, cascadeActions);
                        htmlSelect.change(onChangeFn);
                }
            }
            prevBindingListId   = bindingListId;
            selectedParentId    = selectedTargetId;
        }
    }

    //if cascadeActions exists, call them before calling "_bindSelectListColumns" method recursively..
    if ( cascadeActions != undefined && cascadeActions.length > 0 )
    {
        for(var i=0; i < cascadeActions.length; i++)
        {
            cascadeActions[i].call(this);
        }
    }
}
function doRecursiveBinding(idGrid, currentRowId, bindings, index, cascadeActions, event)
{
    //var triggerListId = event.srcElement.id;
    var triggerListId = event.currentTarget.id; //Fix for Firefox as event's srcElement property is getting 'undefined'..
    var triggerListIndex = index;

    //if cascadeActions exists, call them before calling "_bindSelectListColumns" method recursively..
    if ( cascadeActions != undefined && cascadeActions.length > 0 )
    {
        for(var i=0; i < cascadeActions.length; i++)
        {
            cascadeActions[i].call(this);
        }
    }

    _bindSelectListColumns(idGrid, currentRowId, bindings, triggerListId, triggerListIndex, cascadeActions);
}
function _getSelectListColumns(idGrid)
{
    var selectCols = new Array();
    var colModel = _getColModel(idGrid);
    for (var i=0; i < colModel.length; i++)
    {
        if ( colModel[i].editable == true && colModel[i].edittype == "select" )
        {
            selectCols[selectCols.length] = colModel[i].name;
        }
    } 
    return selectCols;
}
//#endregion

/*#region Formatter Functions */
//Currency..
function _currencyFormatter(cellvalue, options, rowObject)
{
    return Helpers.LocalizationHelper.Currency + cellvalue;
}
function currencyUnformatter(cellvalue, options)
{
    return cellvalue.replace(Helpers.LocalizationHelper.Currency, "");
}
//Decimal..
function _decimalFormatter(cellValue, options, rowObject)
{
    if (cellValue == undefined)
        return cellValue;

    //get decimal separator..
    var decimalSeparator = Helpers.LocalizationHelper.DecimalSeparator;

    //replace decimalSeparator for a "." (in order to be able to parse to Float properly..)
    cellValue = cellValue.replace(decimalSeparator, "*");
    cellValue = cellValue.replace("*", ".");

    //parse as Float and return conversion fixed to 2 decimal places..
    cellValue = parseFloat(cellValue).toFixed(2);

    //give localised format..
    cellValue = cellValue.replace(".", decimalSeparator);

    return cellValue;
}
function _imageFormatter(cellValue, options, rowObject)
{
    return '<img src="' + cellvalue + '" />';
}
function _imageUnformatter(cellvalue, options, cell)
{
    return $('img', cell).attr('src');
}
//#endregion

/*#region Edit Validations */
function _validateDecimal(value, name)
{
    /*
    value = value.replace(',', '.');
    var isNumeric = $.isNumeric(value);
    if (!isNumeric)
    {
        return [false, "is not a valid value for column " + name + "."];
    }
    else
    {
        return [true, null];
    }
    */
    var isValid = DateTimeHelper.Validate.asDecimal(value);
    if ( isValid )
        return [true, null];
    else
        return [false, "is not a valid value for column " + name + "."];
}
//#endregion

/*#region Visual Properties */
function _adjustSizeToFitIntoDialog(idGrid, idDialog, dialogWidth, dialogHeight) 
{
    var dialog = $("#" + idDialog);
    var offset = parseInt(dialog.css("padding-left")) + parseInt(dialog.css("padding-right")) + parseInt(dialog.css("margin-left")) + parseInt(dialog.css("margin-right"));
    _setWidth(idGrid, dialogWidth - offset - 10);
    _setHeight(idGrid, dialogHeight - offset - 110);
}
function _setWidth(idGrid,width)
{
    $("#" + idGrid).jqGrid('setGridWidth', width);
}
function _setHeight(idGrid, height)
{
    $("#" + idGrid).jqGrid('setGridHeight', height);
}
function _toggleColumnVisibility(idGrid, colName)
{
    var action = '';
    var column = $("#" + idGrid + "_" + colName);

    if (column.hasClass('not-visible'))
        action = 'showCol';
    else
        action = 'hideCol';

    $("#" + idGrid).jqGrid(action, colName);
    column.toggleClass('not-visible');

    //just to preserve jqGrid width..
    var grid = _getGrid(idGrid);
    _setWidth(grid.IdGrid, grid.Width);
}
//#endregion

function _getTotalRows(idGrid)
{
    //var grid = _getGrid(idGrid);
    var totalRecords = $("#" + idGrid).jqGrid('getGridParam', 'records');
    return totalRecords;
}
function _getTotalRowsPerPage(idGrid)
{
    var currentRecords = $("#" + idGrid).getRowData().length;
    //alternative: var currentRecords = $("#" + idGrid).getGridParam("reccount");
    return currentRecords;
}
function _hideRowHeaderCheckbox(idGrid)
{
    $("#cb_" + idGrid).css("visibility", "hidden");
}
function _hideRowCheckbox(idGrid, idRow)
{
    $("#jqg_" + idGrid + "_" + idRow).css("visibility", "hidden");
}
function _showRowCheckbox(idGrid, idRow)
{
    $("#jqg_" + idGrid + "_" + idRow).removeAttr("visibility");
}
function _disableRowCheckbox(idGrid, idRow)
{
    $("#jqg_" + idGrid + "_" + idRow).attr("disabled", true);
}
function _enableRowCheckbox(idGrid, idRow)
{
    $("#jqg_" + idGrid + "_" + idRow).removeAttr("disabled");
}
function _disableAllCheckboxes(idGrid)
{
    var grid = _getGrid( idGrid );
    var checkboxes = $("tr.jqgrow > td > input.cbox", grid[0] );
        checkboxes.attr("disabled", "disabled");
}
function _getRowCheckbox( idGrid, idRow )
{
    var checkbox = $("#jqg_" + idGrid + "_" + idRow);
    if ( checkbox.length > 0 )
        return checkbox[0];
    else
        return null;
}
function _getAllRowsCheckboxes(idGrid)
{
    return $("tr.jqgrow > td > input[type='checkbox']:checked", $("#" + idGrid) );
}
function _getAllRows(idGrid, includeHeader)
{
    return $( "#" + idGrid + " tr" + ( includeHeader ? "" : ":not(.jqgfirstrow)" ) );
}
function _getRowHeader( idGrid )
{
    var header = $( "#" + idGrid + " jqgfirstrow" );
    return header;
}
function _clearGridData(idGrid)
{
    $("#" + idGrid).jqGrid('clearGridData');
}
function _destroyGrid(idGrid)
{
    /*
        The method GridDestroy clears all the html associated with the grid and unbinds all events.
        The method GridUnload clears all, but the empty element stay on the page.
    */
    return $("#" + idGrid).GridUnload();
}
function _groupRows(idGrid, columnName, text)
{
    var grid = $("#" + idGrid);
        //grid.jqGrid
        //    ({
        //        grouping: true,
        //        groupingView:
        //        {
        //            groupField: [columnName],
        //            groupColumnShow: [false],
        //            groupText: [title]
        //        },
        //    });
        grid[0].p.groupingView.groupText[0] = '<span class="jqGridRowGroupHeader" >' + text + '</span>';
        grid.jqGrid('groupingGroupBy', columnName);

        grid = _getGrid(idGrid);
        grid.IsGroupingRows = true;

    var toggler = _generateRowGroupNodeToggler(idGrid);
    $("#gbox_" + idGrid).parent().prepend(toggler);
        toggler = $(toggler)[0];
    $("#" + toggler.id).click(function ()
    {
        var expanded =  $(this).attr("expanded") == "true" ? true : false;
                        $(this).attr("expanded", !expanded);
        var lnk = $("#lnkToggleNodes_" + idGrid);
            lnk.text(expanded ? "Expandir todos" : "Colapsar todos");
        var img = $("#imgToggleNodes_" + idGrid);
            img.attr("src", expanded ? "Images/16x16/expandir.png" : "Images/16x16/colapsar.png");
        _expandAllRowGroups(idGrid.replace("_Grid", ""), !expanded);
    });

    $("#" + toggler.id).hover
    (
        function () { $(this).css("text-decoration", "underline"); },
        function () { $(this).css("text-decoration", "none"); }
    );
}
function _removeRowGrouping(idGrid)
{
    $("#" + idGrid).jqGrid('groupingRemove', true);
}
function _expandAllRowGroups(idGrid, expanded)
{
    var icon = expanded ? "plus" : "minus";
    $("#" + idGrid + "_Grid .ui-icon-circlesmall-" + icon).trigger("click");
}
function _getRowGroupHeaders(idGrid)
{
    return $(".jqgroup", $("#" + idGrid));
}
function _getRowGroupHeader(idGrid, index)
{
    return $("#" + idGrid + "ghead_" + index);
}
function _setGroupedRowsHeaderStyles(idGrid)
{
    var grid = _getGrid(idGrid);
    var styles = grid.GroupedRowsHeaderStyles;
    var groupedRowHeaders = _getRowGroupHeaders(idGrid);
    for (var i = 0; i < groupedRowHeaders.length; i++)
    {
        var groupHeader = _getRowGroupHeader(idGrid, i);
        var keys = Object.keys(styles);
        for (var j = 0; j < keys.length; j++)
        {
            groupHeader.css(keys[j], styles[keys[j]]);
        }
    }
}
function _getRowGroupHeaderText(idGrid, index)
{
    var groupHeader     = _getRowGroupHeader(idGrid, index);
    var groupHeaderText = groupHeader.find("td").find(".jqGridRowGroupHeader");
    return groupHeaderText;
}
function _setRowGroupHeaderText(idGrid, index, text)
{
    var groupHeaderText = _getRowGroupHeaderText(idGrid, index);
        groupHeaderText.html(text);
}
function _generateRowGroupNodeToggler(idGrid)
{
    var toggle  = '<span id="btnToggleNodes_' + idGrid + '" expanded="false" style="cursor:pointer;" >';
        toggle += '<img id="imgToggleNodes_' + idGrid + '" src="Images/16x16/expandir.png" />';
        toggle += '<a id="lnkToggleNodes_' + idGrid + '" style="vertical-align:middle; font-weight:normal; color:black;" >Expandir todos</a>';
        toggle += '</span>';
    return toggle;
}
function _groupColumns(idGrid, groupInfo)
{
    /*
        <groupInfo> expected data structure: [ { startColumnName: <string>, numberOfColumns: <integer>, titleText: <string> }, { .. } ]
    */
    for (var i = 0; i < groupInfo.length; i++)
    {
        var text = groupInfo[i].titleText;
        groupInfo[i].id         = idGrid + '_colHeader_' + text; 
        groupInfo[i].titleText  = '<span id="' + idGrid + '_colHeader_' + text + '" class="jqGridGroupHeaderColumn" >' + text + '</span>';
    }

    $("#" + idGrid).jqGrid('setGroupHeaders',
    {
        useColSpanStyle: true,
        groupHeaders: groupInfo
    });
        
    var grid = _getGrid(idGrid);
        grid.IsGroupingColumns = true;
}
function _getColumnGroupHeaders(idGrid) 
{
    return $("#" + idGrid)[0].p.groupHeader.groupHeaders;
}
function _getColumnHeadersPerLevel(idGrid, levelNumber)
{
    var level = "";
    switch ( levelNumber )
    {
        case 1:
            level = "second";
            break;
        case 2:
            level = "third";
            break;   
    }
    return $("table[aria-labelledby=gbox_" + idGrid + "] tr[role=rowheader].jqg-" + level + "-row-header th");   
}
function _setGroupedColumnsHeaderStyles(idGrid)
{
    var grid = _getGrid(idGrid);
    var styles = grid.GroupedColumnsHeaderStyles;
    var secondLevelHeaders = _getColumnHeadersPerLevel(grid.IdGrid, 2);
    for (var i = 0; i < secondLevelHeaders.length; i++)
    {
        var groupHeader = secondLevelHeaders[i];
        var keys = Object.keys(styles);
        for (var j = 0; j < keys.length; j++)
        {
            $(groupHeader).css(keys[j], styles[keys[j]]);
        }
    }
}
function _displaySearchDialog(idGrid, position)
{
    var grid = $("#" + idGrid);
        grid.jqGrid('searchGrid');

    var gridSelector    = $.jgrid.jqID(grid[0].id);
    var gbox            = $("#gbox_" + gridSelector);
    var gridContainer   = gbox.parent();
    var searchDialog    = $("#searchmodfbox_" + gridSelector);

    if ( position != null )
    {
        switch (position)
        {
            case "bottom":
                searchDialog.insertAfter(gridContainer);
                $("<br>").insertAfter(gridContainer);
                break;
            case "top":
                searchDialog.insertBefore(gridContainer);
                $("<br>").insertBefore(gridContainer);
                break;
        }

        searchDialog.css({ position: "relative", zIndex: "auto", top: "0px", left: "0px" });
        searchDialog.find("a.ui-jqdialog-titlebar-close").remove(); //remove search dialog's 'close' button
        searchDialog.find(".jqResize").remove(); //remove search dialog resizer;
                
        var searchDialogTitleBar = $("#searchhdfbox_" + gridSelector);
            searchDialogTitleBar.unbind( "mousedown" ); //remove event that makes search dialog draggable
            searchDialogTitleBar.css("cursor", "default"); //remove cursor = move
    
        $(".ui-widget-overlay").remove(); //remove overlay    
    }
}

/* Helper functions */
function __fixGroupedColumnsWidth(idGrid)
{
    /*
        tr.jqg-second-row-header => First level column headers
        tr.jqg-third-row-header  => Second level column headers
    */
    var firstLevelHeaders = _getColumnHeadersPerLevel(idGrid, 1);
    for (var i = 0; i < firstLevelHeaders.length; i++)
    {
        var header  = $(firstLevelHeaders[i]);

        var columnName = header[0].id.replace(idGrid + "_", "");
        var columnInfo = _getColModelColumn(idGrid, "name", columnName);

        var col     = $("table[id=" + idGrid + "] td[aria-describedby=" + header.attr("id") + "]");
            header.attr("display", "inline-block").attr("width", col.css("width"));
        if ( columnInfo != null )
            header[0].width = columnInfo.width;
    }

    var jqGridColumnOffset  = isSafari ? 0 : 5; // padding-left (2) + padding-right (2) + border-right (1) = 5
    var colGroupHeaders     = _getColumnGroupHeaders(idGrid);
    for (var i = 0; i < colGroupHeaders.length; i++)
    {
        /* Formula: [ ( column_width * column_count ) + ( jqGrid_column_offset x column_count ) ] - [ (jqGrid_column_offset * 1 ) ] */
        var colHeaderInfo   = colGroupHeaders[i];
        var columnInfo      = _getColModelColumn(idGrid, "name", colHeaderInfo.startColumnName);
        var columnCount     = colHeaderInfo.numberOfColumns;
        var columnWidth     = columnInfo.width;
        $("#" + colHeaderInfo.id).parent().css("width", ( (columnWidth * columnCount) + (jqGridColumnOffset * columnCount) ) - (jqGridColumnOffset) + "px");
    }

    /* 
        When grouping columns, Safari gets the first visible column moved to the second visible column's position, and so on, switching all columns position one position to the right
        This fix targets this issue
    */
    var grid = _getGrid(idGrid);
    if ( isSafari && !grid.MultiSelect )
    {
        var tr = $("#" + idGrid + " tr.jqgrow.ui-row-ltr");
        var firstVisibleColumn = tr.find('td:visible:first');
            firstVisibleColumn.css("float", "left");
    }
}